﻿using Abp.Application.Services;
using Abp.Auditing;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.AutoMapper;
using Abp.Events.Bus;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RMM.Authorization;
using RMM.Authorization.Tenants;
using RMM.Core.Entity.Users;
using RMM.Core.UserService;
using RMM.FrameWork;
using RMM.IdGen;
using RMM.UserAppService.Dtos;
using RMM.Users.Dtos;
using RMM.Users.Events;
using RMM.WeChatPay;
using RMM.WeChats;
using Senparc.Weixin.MP.AdvancedAPIs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Configuration;

namespace RMM.UserAppService
{
    public class UserAppService : ApplicationService, IUserAppService
    {
        private string appId = WebConfigurationManager.AppSettings["AppId"]?.ToString();
        private string appSecret = WebConfigurationManager.AppSettings["AppSecret"]?.ToString();
        public IEventBus EventBus { get; set; }
        public IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.Current.GetOwinContext().Authentication;
            }
        }
#if DEBUG
        private string url = "http://localhost:61755/weixin/GetOAuth2Token?userName={0}";
#else
        private string url = "https://uapi.rmmll.com/weixin/GetOAuth2Token?userName={0}";
#endif
        private readonly IUserService _userService;
        private readonly LogInManager _logInManager;
        private readonly UserManager _userManager;
        private readonly UserExtendService _userExtendService;
        private readonly IWeChatAppService _weChatAppService;
        private readonly UIDManager UIDManager;

        public UserAppService(IUserService userService
            , LogInManager logInManager
            , UserManager userManager
            , UserExtendService userExtendService
            , IWeChatAppService weChatAppService
            , UIDManager uIDManager)
        {
            _userService = userService;
            _logInManager = logInManager;
            _userManager = userManager;
            _userExtendService = userExtendService;
            _weChatAppService = weChatAppService;
            UIDManager = uIDManager;
            EventBus = NullEventBus.Instance;
        }

        

        public async Task<UserDto> GetUserDetailAsync(long userId)
        {
            var user = await _userService.FirstOrDefaultAsync(p => p.Id == userId && p.UserType == 1);
            return user.MapTo<UserDto>();
        }

        public async Task<ResultDto> WxLoginAsync(string code)
        {
            try
            {
                var url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
                url = string.Format(url, appId, appSecret, code);
                var loginDto = await CommonHelper.GetAsync<WxLoginDto>(url);
                if (CommonHelper.Check(loginDto.errcode))
                {
                    return ResultDto.Fail(loginDto.errmsg);
                }

                //检查注册
                var check = await CheckUserByUnionOrOpenId(loginDto.openid);
                //未注册
                if (!check)
                {
                    return ResultDto.NoRegister("用户未注册");
                }

                //登陆
                var login = await LoginAsync(loginDto.openid);

                if (!string.IsNullOrEmpty(login))
                {
                    return ResultDto.Success(login);
                }
                return ResultDto.Failed;
            }
            catch (Exception ex)
            {
                return ResultDto.Fail(JsonConvert.SerializeObject(ex.Message + "-------" + ex.StackTrace.ToString()));
            }
        }

        public async Task<string> Register(RegisterInputDto dto)
        {
            Logger.Error(JsonConvert.SerializeObject(dto));
            var url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
            url = string.Format(url, appId, appSecret, dto.jsCode);
            var json = CommonHelper.Get<WechatUserInfoDto>(url);

            var result = WX_AES_decrypt.Decrypt<WechatUserInfoDto>(dto.encryptedData, dto.iv, json.session_key);
            #region userModel
            var u = new User();
            u.OpenId = result.openid;
            u.UnionID = result.unionid;
            u.Name = result.nickname;
            u.NickName = result.nickname;
            u.UserName = result.nickname;
            u.Surname = result.nickname;
            u.TenantId = 1;
            u.Sex = result.sex - 1;
            u.Status = 1;
            u.Address = result.province + result.city;
            u.UserHead = result.headimgurl;
            u.Id = UIDManager.CreateId();

            u.UserType = 1;
            u.GradeId = 1;
            u.ReferralUserId = 0;
            u.EmailAddress = "RMM@qq.com";
            u.Password = "123";
            u.AccessFailedCount = 0;
            u.IsLockoutEnabled = true;
            u.IsPhoneNumberConfirmed = false;
            u.SecurityStamp = "123";
            u.IsTwoFactorEnabled = false;
            u.IsEmailConfirmed = false;
            u.IsActive = true;
            u.IsDeleted = false;
            u.Mobile = "";
            u.CreationTime = DateTime.Now;
            u.Id = UIDManager.CreateId();
            Logger.Error(JsonConvert.SerializeObject(u)); 
            #endregion
            await _userManager.AddUserAsync(u);

            await UnitOfWorkManager.Current.SaveChangesAsync();

            return result.openid;
        }


        public async Task<string> LoginAsync(string id)
        {
            //获取用户信息
            var userDto = await GetUserByUnionOrOpenId(id);
            if (userDto == null)
            {
                throw new Exception("Login Failed");
            }

            //登陆dto
            var userLoginInput = new UserLoginInputDto()
            {
                User = userDto,
                LoginProvider = "Wechat",
                ProviderKey = $"{userDto.UnionID}{userDto.OpenId}"
            };
            var hasLogin = (await _userManager.GetLoginsAsync(userDto.Id)).FirstOrDefault(x => x.LoginProvider == userLoginInput.LoginProvider && x.ProviderKey == userLoginInput.ProviderKey);

            if (hasLogin == null)
            {
                await _userManager.AddLoginAsync(userDto.MapTo<User>(), new UserLoginInfo(userLoginInput.LoginProvider, userLoginInput.ProviderKey));
                await UnitOfWorkManager.Current.SaveChangesAsync();
            }

            var login = new UserLoginInfo(userLoginInput.LoginProvider, userLoginInput.ProviderKey);
            var loginResult = await _logInManager.LoginAsync(login);
            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    var identity = await _userManager.CreateIdentityAsync(userDto.MapTo<User>(), DefaultAuthenticationTypes.ApplicationCookie);
                    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                    AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, identity);
                    url = string.Format(url, userDto.OpenId);
                    return await CommonHelper.PostAsync<string>(url, null);
                default:
                    throw new Exception("Login Failed");
            }
        }


        private async Task<UserDto> GetUserByUnionOrOpenId(string id)
        {
            var user = new User();
            user = await _userService.FirstOrDefaultAsync(p => p.UnionID == id);
            if (user == null)
            {
                user = await _userService.FirstOrDefaultAsync(p => p.OpenId == id);
            }

            return user?.MapTo<UserDto>();
        }

        /// <summary>
        /// 检查用户是否注册过
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> CheckUserByUnionOrOpenId(string id)
        {
            User user;
            user = await _userService.FirstOrDefaultAsync(p => p.UnionID == id);
            if (user == null)
            {
                user = await _userService.FirstOrDefaultAsync(p => p.OpenId == id);
            }

            return user == null ? false : true;
        }

        public async Task<ResultDto> CheckUser(string code)
        {
            var url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
            url = string.Format(url, appId, appSecret, code);
            var loginDto = await CommonHelper.GetAsync<WxLoginDto>(url);

            var b = await CheckUserByUnionOrOpenId(loginDto.openid);
            return b ? ResultDto.Successed : ResultDto.NoRegister("");
        }

        public object GetUsers()
        {
            return AbpSession.UserId ?? 0;
        }

        public async Task LoginTest()
        {
            var url = "http://localhost:61755/weixin/GetOAuth2Token?userName=%E7%94%9F%E5%91%BD%E4%B8%8D%E6%81%AF%EF%BC%8C%E5%A5%8B%E6%96%97%E4%B8%8D%E6%AD%A2&pwd=123";
            var c = await CommonHelper.PostAsync<object>(url, null);
        }
    }
}
